package com.gt.facebook;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;

import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

import com.facebook.android.Util;

public class FbConnection {
	private static final String TAG="FbConnection";
	
	
	private static final int TIMEOUT_CONNECT = 20 * 1000;
	private static final int TIMEOUT_READ = TIMEOUT_CONNECT;
	
	//
	private boolean isReady=false;
	private HttpURLConnection httpUrlConnection = null;
	private OutputStream outputStream = null;
	private InputStream inputStream = null;
	private boolean isForceClose=false;

	public String openUrl(String url, String method, Bundle params)
			throws MalformedURLException, IOException, ForceCloseIOException {
		try {
			isReady=false;
			isForceClose = false;
			return openUrlFb(url, method, params);
		} catch (MalformedURLException e) {
			Log.e(TAG, "openUrl>>>MalformedURLException>>>isForceClose="+ isForceClose);
			e.printStackTrace();
			if (isForceClose) {
				isForceClose = false;
				throw new ForceCloseIOException();
			} else {
				throw e;
			}
		} catch (IOException e) {
			Log.e(TAG, "openUrl>>>IOException>>>isForceClose=" + isForceClose);
			e.printStackTrace();
			if (isForceClose) {
				isForceClose = false;
				throw new ForceCloseIOException();
			} else {
				throw e;
			}
		} finally {
			Log.e(TAG, "openUrl>>>finally>>>isForceClose=" + isForceClose);
			close();
			isForceClose = false;
			isReady=true;
		}

	}

	private String openUrlFb(String url, String method, Bundle params) throws MalformedURLException, IOException,ForceCloseIOException {
		// random string as boundary for multi-part http post
		String strBoundary = "3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f";
		String endLine = "\r\n";

		OutputStream os = null;

		if (method.equals("GET")) {
			url = url + "?" + Util.encodeUrl(params);
		}
		Util.logd("Facebook-Util", method + " URL: " + url);
		
		if (isForceClose) {
			throw new ForceCloseIOException();
		}
		
		final HttpURLConnection conn = (HttpURLConnection) new URL(url)
				.openConnection();
		httpUrlConnection = conn;
		conn.setRequestProperty("User-Agent", System.getProperties()
				.getProperty("http.agent") + " FacebookAndroidSDK");

		conn.setConnectTimeout(TIMEOUT_CONNECT);
		conn.setReadTimeout(TIMEOUT_READ);
		
		if (isForceClose) {
			throw new ForceCloseIOException();
		}

		if (!method.equals("GET")) {
			Bundle dataparams = new Bundle();
			for (String key : params.keySet()) {
				Object parameter = params.get(key);
				if (parameter instanceof byte[]) {
					dataparams.putByteArray(key, (byte[]) parameter);
				}
			}

			// use method override
			if (!params.containsKey("method")) {
				params.putString("method", method);
			}

			if (params.containsKey("access_token")) {
				String decoded_token = URLDecoder.decode(params
						.getString("access_token"));
				params.putString("access_token", decoded_token);
			}

			conn.setRequestMethod("POST");
			conn.setRequestProperty("Content-Type",
					"multipart/form-data;boundary=" + strBoundary);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setRequestProperty("Connection", "Keep-Alive");

			if (isForceClose) {
				throw new ForceCloseIOException();
			}
			
			conn.connect();

			if (isForceClose) {
				throw new ForceCloseIOException();
			}
			
			outputStream = conn.getOutputStream();
			os = new BufferedOutputStream(outputStream);

			
			if (isForceClose) {
				throw new ForceCloseIOException();
			}
			
			
			
			os.write(("--" + strBoundary + endLine).getBytes());
			os.write((Util.encodePostBody(params, strBoundary)).getBytes());
			os.write((endLine + "--" + strBoundary + endLine).getBytes());
			
			
			if (isForceClose) {
				throw new ForceCloseIOException();
			}

			if (!dataparams.isEmpty()) {

				for (String key : dataparams.keySet()) {
					os.write(("Content-Disposition: form-data; filename=\""
							+ key + "\"" + endLine).getBytes());
					os.write(("Content-Type: content/unknown" + endLine + endLine)
							.getBytes());
					os.write(dataparams.getByteArray(key));
					os.write((endLine + "--" + strBoundary + endLine)
							.getBytes());

				}
			}
			os.flush();
		}
		
		if (isForceClose) {
			throw new ForceCloseIOException();
		}

		String response = "";
		try {
			inputStream = conn.getInputStream();
			response = read(inputStream);
		} catch (FileNotFoundException e) {
			// Error Stream contains JSON that we can parse to a FB error
			inputStream = conn.getErrorStream();
			response = read(inputStream);
		}
		return response;
	}

	public void forceClose(){
		this.isForceClose=true;
		this.close();
	}
	
	private void close() {
		if (outputStream != null) {
			try {
				outputStream.close();
				outputStream=null;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (inputStream != null) {
			try {
				inputStream.close();
				inputStream=null;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (httpUrlConnection != null) {
			try {
				httpUrlConnection.disconnect();
				httpUrlConnection=null;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private static String read(InputStream in) throws IOException {
		StringBuilder sb = new StringBuilder();
		BufferedReader r = new BufferedReader(new InputStreamReader(in), 1000);
		for (String line = r.readLine(); line != null; line = r.readLine()) {
			sb.append(line);
		}
		in.close();
		return sb.toString();
	}

}
